// HMAC-based score verification system
const SECRET_KEY = 'trickle_color_game_v1'; // This is just for demo, in production should use a more complex key
const VERIFICATION_START_TIME = '2024-12-21T14:09:59.128Z'; // When we started requiring verification

async function generateHMAC(message) {
    try {
        // Convert the secret key and message to ArrayBuffer
        const encoder = new TextEncoder();
        const keyData = encoder.encode(SECRET_KEY);
        const messageData = encoder.encode(message);

        // Import the key
        const key = await crypto.subtle.importKey(
            'raw',
            keyData,
            { name: 'HMAC', hash: 'SHA-256' },
            false,
            ['sign']
        );

        // Sign the message
        const signature = await crypto.subtle.sign(
            'HMAC',
            key,
            messageData
        );

        // Convert to base64
        return btoa(String.fromCharCode(...new Uint8Array(signature)));
    } catch (error) {
        reportError(error);
        return null;
    }
}

async function verifyHMAC(message, signature) {
    try {
        // Convert the secret key and message to ArrayBuffer
        const encoder = new TextEncoder();
        const keyData = encoder.encode(SECRET_KEY);
        const messageData = encoder.encode(message);

        // Import the key
        const key = await crypto.subtle.importKey(
            'raw',
            keyData,
            { name: 'HMAC', hash: 'SHA-256' },
            false,
            ['verify']
        );

        // Decode the signature from base64
        const signatureData = new Uint8Array(
            atob(signature).split('').map(c => c.charCodeAt(0))
        );

        // Verify the signature
        return await crypto.subtle.verify(
            'HMAC',
            key,
            signatureData,
            messageData
        );
    } catch (error) {
        reportError(error);
        return false;
    }
}

// Generate a verification token for a score
async function generateScoreToken(score, playerName, timestamp) {
    try {
        // Combine the score data into a single string
        const message = `${playerName}:${score}:${timestamp}`;
        return await generateHMAC(message);
    } catch (error) {
        reportError(error);
        return null;
    }
}

// Verify a score token
async function verifyScoreToken(score, playerName, timestamp, token) {
    try {
        const message = `${playerName}:${score}:${timestamp}`;
        return await verifyHMAC(message, token);
    } catch (error) {
        reportError(error);
        return false;
    }
}

// Verify a score object
async function verifyScoreObject(scoreObj) {
    try {
        const scoreTimestamp = new Date(scoreObj.objectData.timestamp);
        const verificationStartTime = new Date(VERIFICATION_START_TIME);
        const now = new Date();

        // If timestamp is in the future, it's definitely invalid
        if (scoreTimestamp > now) {
            console.log('Invalid: Future timestamp detected:', scoreObj);
            return false;
        }

        // If the score was recorded after verification start time
        if (scoreTimestamp > verificationStartTime) {
            // No verification token after we started requiring it
            if (!scoreObj?.objectData?.verificationToken) {
                console.log('Invalid: Missing verification token:', scoreObj);
                return false;
            }

            return await verifyScoreToken(
                scoreObj.objectData.score,
                scoreObj.objectData.playerName,
                scoreObj.objectData.timestamp,
                scoreObj.objectData.verificationToken
            );
        }

        // Scores before verification start time are considered valid
        return true;
    } catch (error) {
        reportError(error);
        return false;
    }
}
